#pragma once

namespace DirectUI
{
	interface __declspec(uuid("E5A9EF14-80CF-4C0D-B3F4-E883F02CBC3D")) IUITimer : public IUIObject
	{
		virtual BOOL	StartTimer(DWORD DueTime, DWORD Period) = 0;
		virtual void	StopTimer() = 0;
	};

	class CUITimer : public CUINoAggregateObjectImplHelper<IUITimer, CUITimer, IUITimer>
	{
		DECLARE_CLASS(CUITimer, Timer)
	public:
		CUITimer()
			: m_hTimerHandle(INVALID_HANDLE_VALUE)
			, m_bCloseTimer(FALSE)
		{

		}
		virtual ~CUITimer()
		{
			ClearTimer();
		}

		virtual HRESULT QueryInterface( const GUID& guid, void** lppObject ) 
		{
			if ( guid == __uuidof(IUITimer) )
			{
				if (lppObject)
				{
					*lppObject = (IUITimer*)this;
					AddRef();
				}
				return S_OK;
			}

			return __super::QueryInterface(guid, lppObject);
		}

		virtual void OnTimer() { }
		virtual void TimerOwnerFreePointer() { }

		static void CALLBACK TimerProc(void* lpParametar, BOOLEAN TimerOrWaitFired)
		{
			CUIObjectPtr<IUIObject> sp = (IUIObject*)lpParametar;
			if ( sp )
			{
				CUITimer* pUiTimer = (CUITimer*)lpParametar;
				if ( pUiTimer->m_bCloseTimer )
					pUiTimer->ClearTimer();
				pUiTimer->AddRef();
				::PostThreadMessage(GetUICore()->GetMainThreadID(), GetUICore()->GetUIInternalMessageID(), uimsgid_Timer, (LPARAM)lpParametar);
			}
		}

		virtual BOOL StartTimer(DWORD DueTime, DWORD Period)
		{
			m_bCloseTimer = FALSE;
			this->AddRef();
			return ::CreateTimerQueueTimer(
				&m_hTimerHandle,
				NULL,
				&CUITimer::TimerProc,
				this,
				DueTime,
				Period,
				WT_EXECUTEINTIMERTHREAD);
		}

		virtual void StopTimer() { m_bCloseTimer = TRUE; }
		BOOL IsTimerClosed() { return m_bCloseTimer; }

	private:

		void ClearTimer()
		{
			if ( m_hTimerHandle != INVALID_HANDLE_VALUE )
			{
				DeleteTimerQueueTimer(NULL, m_hTimerHandle, NULL);
				m_hTimerHandle = INVALID_HANDLE_VALUE;
			}
		}

		HANDLE			m_hTimerHandle;
		volatile BOOL	m_bCloseTimer;
	};
}